/************************************************************************
  * Copyright(c) 2023 Levetop Semiconductor Co.,Led. All rights reserved.
  * @file     tp_ctp.c
  * @author   UartTFT Application Team
  * @version  V0.0.1
  * @date     2023-01-01
  * @brief    
 *************************************************************************/

#include "tp_ctp.h"
#include "i2c_drv.h"
#include "eport_drv.h"
#include "spi_drv.h"
#include "tp_iic.h"
#include "function_drv.h"

uint8_t ctp_press_t;

#if (LT_TOUCH_FLAG == 2)

uint8_t READ_BUFF[128];
uint8_t WRITE_BUFF[20];
uint8_t ctp_active_index = 0;

uint8_t gt911flag = 0;
uint8_t cjt540flag = 0;
uint8_t ft5216flag = 0;
uint8_t CST816Dflag = 0;
uint8_t chsc5xxxflag = 0;
uint8_t CTP_ADDR = 0;
uint16_t X_Output_Max, Y_Output_Max;

uint8_t CTP_ConfigureBuff[186] =
	{
		0x41, 0x00, 0x04, 0x58, 0x02, 0x0A, 0x0D, 0x00, 0x01, 0xC8,
		0x28, 0x0F, 0x50, 0x32, 0x03, 0x05, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x29, 0x77,
		0x17, 0x15, 0x31, 0x0D, 0x00, 0x00, 0x00, 0x9A, 0x03, 0x2D,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x0F, 0x37, 0x94, 0xC5, 0x02, 0x08, 0x00, 0x00, 0x00,
		0x9B, 0x11, 0x00, 0x7A, 0x16, 0x00, 0x62, 0x1C, 0x00, 0x4C,
		0x25, 0x00, 0x3D, 0x30, 0x00, 0x3D, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x01, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
		0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0xFF, 0xFF, 0xFF, 0xFF,
		0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x02, 0x04, 0x06, 0x07, 0x08, 0x0A, 0x0C,
		0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x19, 0x1B,
		0x1C, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0xFF, 0xFF, 0xFF,
		0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0xA4, 0x01};

void Checksum(uint8_t *p) // Configuration information check 0x80ff (checked algorithm is correct)
{
	int32_t i = 0;
	uint32_t sum_buffer = 0;

	for (; i < 184; i++)
	{
		sum_buffer += *(p + i);
	}

	*(p + 184) = ~sum_buffer + 1;
//	printf("%x\r\n", *(p + 184));
}

//---------------------------------clear buffer-------------------------//
void ClearBuff(uint8_t *p)
{
	int32_t i = 0;
	for (; i < 20; i++)
	{
		*(p + i) = 0;
	}
}

/*************Get the interrupt pin level*************/
uint8_t TP_Get_INT(void)
{
	if (CTP_GET_INT_BIT)
		return 1;
	else
		return 0;
}

/******************************************************************************
 * DESCRIPTION: Write touch screen register
 ******************************************************************************/
uint8_t CTP_BufferWrite(uint8_t *pBuffer, uint32_t WriteAddr, uint8_t AddrByte, uint16_t NumByte)
{
	uint32_t addr;

	CTI2C_Start();

	CTI2C_write_byte((CTP_ADDR) | 0);
	for (; AddrByte > 0; AddrByte--)
	{
		addr = WriteAddr;
		for (uint8_t i = 1; i < AddrByte; i++)
			addr >>= 8;
		CTI2C_write_byte(addr & 0xFF);
	}

	while (NumByte--)
	{
		CTI2C_write_byte(*pBuffer);
		pBuffer++;
	}

	CTI2C_Stop();

	return 0;
}

/******************************************************************************
 * DESCRIPTION: Read data from the touch screen
 ******************************************************************************/
uint8_t CTP_BufferRead(uint8_t *pBuffer, uint32_t ReadAddr, uint8_t AddrByte, uint16_t NumByte)
{
	uint32_t addr;

	CTI2C_Start();
	CTI2C_write_byte(CTP_ADDR | 0);
	for (; AddrByte > 0; AddrByte--)
	{
		addr = ReadAddr;
		for (uint8_t i = 1; i < AddrByte; i++)
			addr >>= 8;
		CTI2C_write_byte(addr & 0xFF);
	}
	CTI2C_Stop();

	CTI2C_Start();
	CTI2C_write_byte(CTP_ADDR | 0x01);
	for (; NumByte > 1; NumByte--)
	{
		*pBuffer = CTI2C_read_byte(0);
		pBuffer++;
	}
	*pBuffer = CTI2C_read_byte(1);

	CTI2C_Stop();

	return 0;
}

// ������
uint8_t TP_read_XY(void)
{
	uint16_t x, y;
	uint8_t temp = 0;

	if (cjt540flag)
	{

		READ_BUFF[0] = 0;
		CTP_BufferRead(READ_BUFF, 0xD000, 2, 7);
		temp = READ_BUFF[0];
		// printf("temp = 0x%x \r\n",temp);
		if (((temp & 0x0F) >> 1) == 0x03) // buffer status == 1, data valid
		{
			x = (READ_BUFF[1] << 4) | ((READ_BUFF[3] >> 4) & 0x0F);
			y = (READ_BUFF[2] << 4) | (READ_BUFF[3] & 0x0F);

			gTpInfo.x[0] = x;
			gTpInfo.y[0] = y;

			gTpInfo.sta = 1;
			if (gTpInfo.x[0] > LCD_XSIZE_TFT)
				gTpInfo.x[0] = LCD_XSIZE_TFT;
			if (gTpInfo.y[0] > LCD_YSIZE_TFT)
				gTpInfo.y[0] = LCD_YSIZE_TFT;
			if (First_press == 0)
			{
				First_press = 1;
				First_pressX = gTpInfo.x[0];
				First_pressY = gTpInfo.y[0];
			}
			// printf("x=%d y=%d\r\n",x,y);
			// printf("gTpInfo.x=%d gTpInfo.y=%d\r\n",gTpInfo.x[0],gTpInfo.y[0]);

			READ_BUFF[0] = 0xAB;
			CTP_BufferWrite(READ_BUFF, 0xD000, 2, 1);
		}
		else
		{
			gTpInfo.sta = 0;
			First_press = 0;
		}
	}
	else if (gt911flag)
	{
	
		CTP_BufferRead(READ_BUFF, 0x814E, 2, 1);
		temp = READ_BUFF[0] & 0x8F;
		// printf("temp = 0x%x  \r\n",temp);
		if (temp > 0x80) // buffer status ==1 && number of touch points > 0
		{
			CTP_BufferRead(READ_BUFF, 0x814F, 2, 5 * 8); // read
			// printf("track id = 0x%x   \r\n",READ_BUFF[0] ); //track id
			READ_BUFF[0] = 0;
			CTP_BufferWrite(READ_BUFF, 0x814E, 2, 1); // clear

			x = ((READ_BUFF[2] & 0x0F) << 8) | READ_BUFF[1];
			y = ((READ_BUFF[4] & 0x0F) << 8) | READ_BUFF[3];

			gTpInfo.x[0] = x * LCD_XSIZE_TFT / X_Output_Max;
			gTpInfo.y[0] = y * LCD_YSIZE_TFT / Y_Output_Max;
			// printf("x=%d y=%d\r\n",gTpInfo.x[0],gTpInfo.y[0]);

			if (gTpInfo.x[0] > LCD_XSIZE_TFT)
				gTpInfo.x[0] = LCD_XSIZE_TFT;
			if (gTpInfo.y[0] > LCD_YSIZE_TFT)
				gTpInfo.y[0] = LCD_YSIZE_TFT;

			if (First_press == 0)
			{
				First_press = 1;
				First_pressX = gTpInfo.x[0];
				First_pressY = gTpInfo.y[0];
				// printf("First_press  x=%d y=%d\r\n",First_pressX,First_pressY);
			}
			//				printf("x=%d y=%d\r\n",gTpInfo.x[0],gTpInfo.y[0]);

			gTpInfo.sta = 1;
			gTpInfo.readspace = 0;
		}
		else if (gTpInfo.sta && (temp == 0)) // wait data prepare
		{
			gTpInfo.readspace++;
			if (gTpInfo.readspace > 8)
				gTpInfo.sta = 0;
		}
		else
		{
			READ_BUFF[0] = 0;
			CTP_BufferWrite(READ_BUFF, 0x814E, 2, 1);

			gTpInfo.sta = 0;
			gTpInfo.readspace = 0;
			First_press = 0;
		}
	}
	else if (ft5216flag || CST816Dflag)
	{

		CTP_BufferRead(READ_BUFF, 0x02, 1, 1); // Number of touch points
		//printf("READ_BUFF[0]=%d \r\n",READ_BUFF[0]);
		if(READ_BUFF[0] > 1)
		{	
		//Double_finger_flag=0;
		}
		else if(READ_BUFF[0] == 1&&Double_finger_flag==0)
		{
		//Double_finger_flag=1;
		}
		//printf("Double_finger_flag=%d \r\n",Double_finger_flag);
		//else if(READ_BUFF[0] == 0)
		//{
			//Double_finger_flag=0;Double_finger_sum=0;
		//}
		if (READ_BUFF[0] > 0)
		{
			CTP_BufferRead(READ_BUFF, 0x03, 1, 5 * 6);
			temp = READ_BUFF[0] >> 6; // bits 00: press down  01:raise  10:keep press   11:No event
		}
		else
			temp = 3;

		if (temp == 0 || temp == 2)
		{
			x = ((READ_BUFF[0] & 0x0F) << 8) | READ_BUFF[1];
			y = ((READ_BUFF[2] & 0x0F) << 8) | READ_BUFF[3];
			gTpInfo.x[0] = x;
			gTpInfo.y[0] = y;
			
			uint16_t tempx=gTpInfo.x[0], tempy=gTpInfo.y[0];//CJ
			gTpInfo.x[0] = tempy;
			gTpInfo.y[0] = LCD_YSIZE_TFT - tempx;

			if (gTpInfo.x[0] > LCD_XSIZE_TFT)
				gTpInfo.x[0] = LCD_XSIZE_TFT;
			if (gTpInfo.y[0] > LCD_YSIZE_TFT)
				gTpInfo.y[0] = LCD_YSIZE_TFT;

			if (First_press == 0)
			{
				First_press = 1;
				First_pressX = gTpInfo.x[0];
				First_pressY = gTpInfo.y[0];
			}
			//				printf("x=%d y=%d   \r\n",gTpInfo.x[0],gTpInfo.y[0]);
			gTpInfo.sta = 1;
		}
		else if (temp == 3 || temp == 1)
		{
			gTpInfo.sta = 0;
			First_press = 0;
			Double_finger_flag=0;Double_finger_sum=0;disp_lock_pic=0;
		}
	}
	else if (chsc5xxxflag)
	{

		CTP_BufferRead(READ_BUFF, 0x00, 1, 15); //

		temp = READ_BUFF[3] >> 4; // bits 0X00:press down     0X08:keep press   0X04:raise

		if (temp == 0 || temp == 0x08)
		{
			x = ((READ_BUFF[3] & 0x0F) << 8) | READ_BUFF[4];
			y = ((READ_BUFF[5] & 0x0F) << 8) | READ_BUFF[6];

			gTpInfo.x[0] = x;
			gTpInfo.y[0] = y;
			//				printf("x=%d y=%d\r\n",gTpInfo.x[0],gTpInfo.y[0]);

			if (gTpInfo.x[0] > LCD_XSIZE_TFT)
				gTpInfo.x[0] = LCD_XSIZE_TFT;
			if (gTpInfo.y[0] > LCD_YSIZE_TFT)
				gTpInfo.y[0] = LCD_YSIZE_TFT;

			if (First_press == 0)
			{
				First_press = 1;
				First_pressX = gTpInfo.x[0];
				First_pressY = gTpInfo.y[0];
			}
			//printf("x=%d y=%d\r\n",gTpInfo.x[0],gTpInfo.y[0]);
			gTpInfo.sta = 1;
		}
		else if (temp == 0x04)
		{
			gTpInfo.sta = 0;
			First_press = 0;
			
		}
	}
}

uint8_t CTP_Scan(void)
{
	if (ctp_active_index == 1)
	{
		// printf("read\r\n");
		TP_read_XY();
		ctp_active_index = 0;
		return 1;
	}
	else
	{
		return 0;
	}
}

/*****************Initialization function of IO port related to capacitive touch screen************************/
void CTP_IO_Init(void)
{
	uint8_t ack, i;

	cjt540flag = 0;
	gt911flag = 0;
	ft5216flag = 0;

	// IO_Init
	// IOCTRL->I2C_CONTROL_REG |= 0x03;           //Enhance I2C drive capability
	CTP_RST_OUTPUT;
	CTP_INT_OUTPUT;
	CTP_SCL_OUTPUT;
	CTP_SCL_PULLUP;
	CTP_SDA_OUTPUT;
	CTP_SDA_PULLUP;
	CTP_RST_HIGH;
	CTP_INT_HIGH;
	CTP_SCL_HIGH;
	CTP_SDA_HIGH;

	CTP_INT_LOW;
	CTP_RST_LOW;
	DelayMS(2);
	CTP_INT_HIGH;
	DelayMS(2);
	CTP_RST_HIGH;
	DelayMS(10);
	CTP_INT_LOW;
	DelayMS(60);

	CTP_INT_INPUT; // Set as interrupt input
	CTP_INT_INTERRUPT;
	DelayMS(20);

	// slave addr scan
	for (i = 0; i < 128; i++)
	{
		CTI2C_Start();
		ack = CTI2C_write_byte(i << 1);
		CTI2C_Stop();
		if (!ack)
		{
			// printf("addr==0x%x, ack==ok  \r\n",i<<1);
			CTP_ADDR = (i << 1);
			if (CTP_ADDR == 0x28)
			{
				gt911flag = 1;
				CTP_BufferRead(READ_BUFF, 0x8146, 2, 4);
				X_Output_Max = (READ_BUFF[1] << 8 | READ_BUFF[0]);
				Y_Output_Max = (READ_BUFF[3] << 8 | READ_BUFF[2]);
				// printf("X_Output_Max =  %d , %d  \r\n",X_Output_Max,Y_Output_Max);
			}
			else if (CTP_ADDR == 0x34)
				cjt540flag = 1;
			else if (CTP_ADDR == 0x70)
				ft5216flag = 1;
			else if (CTP_ADDR == 0x2a)
				CST816Dflag = 1; // CST816D
			// else if(CTP_ADDR==0xaa)	ST1663iflag	=	1;    //ST1663i
			else if (CTP_ADDR == 0x5C)
				chsc5xxxflag = 1;
			break;
		}
		DelayUS(1);
	}
//	printf("CTP_ADDR = 0x%x \r\n", CTP_ADDR);
}
void CTP_Init(void)
{
	CTP_IO_Init();
	gTpInfo.scan = CTP_Scan;
}

#endif

#if IIC_BUS
void I2C_Slave_TEST(uint8_t sla_addr)
{
	I2C->CR = 0x0;
	I2C->CR |= CR_EN;

	delay(100);

	I2C->CR |= CR_ACKEN;

	I2C->CR |= CR_IEN;
	I2C->CR &= ~CR_MSMOD;

	I2C->SAHR = sla_addr << 1;
	/*Configure interrupts in slave mode*/
	NVIC_Init(3, 3, I2C_1_IRQn, 2);
}

uint16_t Rx_len = 0, Tx_len = 0;
uint16_t reg_addr = 0;
uint8_t flag_IIC_REG[20];
uint16_t ID_IIC_WAV = 0;

// IIC slave transceiver interrupt function
void I2C1_IRQHandler(void)
{
	volatile uint8_t tmp = 0;
	static uint8_t curve_rev_val = 0;
	static uint8_t curve_rev_num = 0;
	static uint8_t curve_rev_tmp = 0;
	static uint16_t curve_rev_data = 0;
	static uint8_t curve_rev_cnt = 0;

	uint8_t i = 0;

	uint8_t i2c_status, i2c_hs_status;

	i2c_status = I2C->CSR;
	i2c_hs_status = I2C->SHSIR;
	
	if ((i2c_hs_status & SLV_HS) != SLV_HS)
	{
		if ((i2c_status & SR_AASLV) == SR_AASLV) //Slave address matching
		{
			I2C->CR &= ~CR_AMIE;			   // Under normal circumstances, turn off the slave address matching interrupt
			if ((i2c_status & SR_RC) == SR_RC) // Receiving is interrupted. The received address and data will come in
			{
				Tx_len = 0;
				if ((I2C->CSR & SR_TF) == SR_TF) // Transmission completion interrupt
				{
					if (Rx_len == 0) // Upper 8 bits of receiving address
					{
						reg_addr = I2C->CDR;
					}
					else if (Rx_len == 1) // Lower 8 bits of receiving address
					{
						reg_addr = (reg_addr << 8) | I2C->CDR;
						//if(reg_addr>=0xF001 && reg_addr<=0xF0FF)
						if (reg_addr >= VAR_CURVE_WS && reg_addr <= VAR_CURVE_WE)
						{
							curve_rev_val = reg_addr & 0xFFF;
							curve_rev_cnt = 0;
							curve_rev_num = 0;
							for (i = 0; i < CURVE_CHANNEL; i++) // Record how many groups of channels
							{
								if (curve_rev_val & (1 << i))
									curve_rev_num++;
							}
						}
					}
					else //receive data
					{
						if (addr < VAR_ADDR_S) // Variable address
						{
							// Direct saving of variable data
							var[2 * reg_addr + Rx_len - 2] = I2C->CDR;
						}
						else if (reg_addr >= VAR_ADDR_S && reg_addr <= VAR_ADDR_E) // Register address
						{
							// WAV register data needs special processing
							if (2 * reg_addr + Rx_len - 2 == 2 * VAR_WAV)
							{
								ID_IIC_WAV = I2C->CDR;
							}
							else if (2 * reg_addr + Rx_len - 2 == 2 * VAR_WAV + 1)
							{
								ID_IIC_WAV = (ID_IIC_WAV << 8) | I2C->CDR;
							}
							// The remaining register data is saved directly
							else
							{
								var[2 * reg_addr + Rx_len - 2] = I2C->CDR;
							}

							if (Rx_len % 2) // The update flag of the corresponding register will be triggered every time 2Bytes are received
							{
								flag_IIC_REG[(2 * (reg_addr - VAR_ADDR) + Rx_len - 2) / 2] = 1;
							}
						}
						//else if(reg_addr>=0xF001 && reg_addr<=0xF0FF)
						else if (reg_addr >= VAR_CURVE_WS && reg_addr <= VAR_CURVE_WE)
						{
							for (i = curve_rev_cnt; i < CURVE_CHANNEL; i++)
							{
								if (curve_rev_val & (1 << i)) // Poll to detect whether 8 channels have triggered updates
								{
									if (Rx_len % 2 == 0)
									{
										curve_rev_data = (I2C->CDR) << 8; // Receive the first byte of curve data
									}
									else if (Rx_len % 2 == 1)
									{
										Curve_buff[i][Curve_count[i]] = curve_rev_data | (I2C->CDR); // Receive the second byte of curve data
										Curve_count[i]++;
										if (Curve_count[i] >= 1024)
										{
											Curve_count[i] = 0;
										}
										curve_update_flag[i] = 1;

										curve_rev_cnt++;
										if (curve_rev_cnt >= curve_rev_num)
											curve_rev_cnt = 0;
									}
									break;
								}
							}
						}
						else // Other addresses only receive but do not process
						{
							i = I2C->CDR;
						}
					}

					Rx_len++;
					I2C->CR |= CR_ACKEN;
				}
				else // Received address
				{
					Rx_len = 0;
					I2C->CR |= CR_ACKEN;
				}
			}
			else // No receive interruption	
			{
				if ((i2c_status & SR_TF) == SR_TF) // Transmission completion interrupt
				{
					Rx_len = 0;
					if ((i2c_status & SR_DACK) == SR_DACK)
					{
						// Direct feedback data
						if (addr < VAR_ADDR_S) // Variable address
						{
							I2C->CDR = var[2 * reg_addr + Tx_len];
						}
						else if (reg_addr >= VAR_ADDR_S && reg_addr <= VAR_ADDR_E) // Register address
						{
							I2C->CDR = var[2 * reg_addr + Tx_len];
						}
						else
						{
							I2C->CDR = 0xFF;
						}

						Tx_len++;
					}
					else
					{
						tmp = I2C->CDR;
						tmp++; // add for warning
					}
				}
				else
				{
					;
				}
			}
		}
		else
		{
			// asm("bkpt");
		}
	}
	else
	{
		I2C->SSHTR = (I2C->SSHTR & 0xc0) | 0x1;
		I2C->SSHTR = I2C->SSHTR | 0x1;

		I2C->SHSIR |= SLV_HS;
	}
}
#endif
